/** 
 * 
 *  该函数用于解析函数的参数，支持多种参数传递方式 
 * 
 * @param patterns 
 * @param args 
 * @param defaultValues 
 * @returns 
 */ 
 
 export default function flexArgs(patterns,args,defaultValues={}){
    if(!Array.isArray(patterns) || patterns.length===0){
        throw new Error('Parameters pattern is required')
    }
    if(!args || args.length===0){
        throw new Error('Arguments is required')
    }

    if(args.length===1 && args[0].constructor === Object && patterns.filter(p=>Object.keys(p).length===1).some(p=>Object.values(p)[0]==="any")){
        // 如果只一个参数,并且是一个{}，并且定义了一个{<x>:"any"}的，
        return {[Object.keys(patterns.filter(p=>Object.keys(p).length===1)[0])[0]]:args[0]}
    }else if(args.length===1 && args[0].constructor === Object && !patterns.filter(p=>Object.keys(p).length===1).some(p=>Object.values(p)[0]===Object)){
        // 如果只一个参数,并且是一个{}，并且没有定义{<>:Object}的，则直接返回整个对象
        return Object.assign({},defaultValues,args[0])
    }

    let values = Object.assign({},defaultValues) 

    // 1. 先匹配参数个数相同的项的pattern
    // 比如args只有两个参数，则只需要过滤出patterns里面两项参数的pattern进行解析
    let argPatterns=patterns.filter((v)=>Object.keys(v).length===args.length)
    for(let i=0;i<argPatterns.length;i++){
        const pattern = argPatterns[i];
        let index = 0;      // 位置参数索引
        let isMached=true
        values =Object.assign({},defaultValues)
        let matchedCount = 0 
        for(let [argName,argType] of Object.entries(pattern)){
            // 如果参数没有类型或类型相符
            try{
                isMached = argType==undefined
                    || argType===null
                    || argType==='any'
                    || argType===args[index].constructor
                    || (typeof(argType)==="string" && argType === args[index].constructor)
                    || (typeof(argType) === "function" && argType===args[index].constructor)                
            }catch {
                isMached = false
            }

            if(isMached){
                matchedCount++
                if(argName in values && values[argName].constructor === Object ){
                    values[argName]=Object.assign({},values[argName],args[index])
                }else{
                    values[argName]=args[index]
                }
            }else{      // 如果有一项不相符，则说明当前模式不匹配，因此进行下一个模式的匹配
                break
            }
            index++
        }
        // 如果全部匹配，则直接返回匹配即可
        if(matchedCount===Object.keys(pattern).length){
            break
        }

    }
    return values


}
